﻿using Ninject;
using Ninject.Activation;
using SoldiHive.Configuration;
using SoldiHive.Core;
using SoldiHive.Core.Adapters;
using SoldiHive.Core.Cache;
using SoldiHive.Core.Crawlers;
using SoldiHive.Core.NodeJs;
using SoldiHive.Core.Parsing;
using SoldiHive.Core.Persistence;
using SoldiHive.Core.Ratings;
using System.Collections.Generic;

namespace SoldiHive.ContractBindings
{
	public static class DI
	{
		public static IKernel Kernel { get; set; }

		static DI()
		{
			DI.Kernel = new StandardKernel();

			DI.Kernel.Bind<IPrinter>().To<Printer>();
			
			DI.Kernel.Bind<IMarketViewer>().To<MarketViewer>();

			DI.Kernel.Bind<IEarningsStatementsCrawler>().To<EarningsStatementsCrawler>();
			DI.Kernel.Bind<ICurrentPriceCrawler>().To<CurrentPriceCrawler>();
			DI.Kernel.Bind<IQuotesCrawler>().To<QuotesCrawler>();
			DI.Kernel.Bind<IRatingsCrawler>().To<RatingsCrawler>();
			DI.Kernel.Bind<IRivalsCrawler>().To<RivalsCrawler>();

			DI.Kernel.Bind<IEarningsStatementsAdapter>().To<NasdaqAdapter>();

			DI.Kernel.Bind<ICurrentPriceAdapter>().To<NasdaqAdapter>();
			DI.Kernel.Bind<IRatingsAdapter>().To<BenzingaAdapter>();
			DI.Kernel.Bind<IRatingsAdapter>().To<MarketwatchAdapter>();
			DI.Kernel.Bind<IRatingsAdapter>().To<NasdaqAdapter>();
			DI.Kernel.Bind<IRatingsAdapter>().To<StreetInsiderAdapter>();
			DI.Kernel.Bind<IRatingsAdapter>().To<YahooAdapter>();
			DI.Kernel.Bind<IEnumerable<IRatingsAdapter>>().ToMethod(ctx => DI.Kernel.GetAll<IRatingsAdapter>());

			DI.Kernel.Bind<IParser>().To<Parser>();
			DI.Kernel.Bind<IRatingStrategy>().To<RatingStrategy>();

			DI.Kernel.Bind<ICompanyRepository>().ToMethod(ctx => DI.GetCompaniesRepository()).InSingletonScope();
			DI.Kernel.Bind<IQuoteRepository>().ToMethod(ctx => DI.GetQuotesRepository()).InSingletonScope();

			DI.Kernel.Bind<IScriptExecutor>().To<ScriptExecutor>();

			DI.Kernel.Bind<ICache>().To<Cache>().InSingletonScope();

			DI.Kernel.Bind<IAdapterConfiguration>().ToMethod(ctx => ConfigurationFactory.GetConfiguration<IAdapterConfiguration>());
			DI.Kernel.Bind<ICacheConfiguration>().ToMethod(ctx => ConfigurationFactory.GetConfiguration<ICacheConfiguration>());
			DI.Kernel.Bind<IScriptExecutorConfiguration>().ToMethod(ctx => ConfigurationFactory.GetConfiguration<IScriptExecutorConfiguration>());
			DI.Kernel.Bind<ICompanyRepositoryConfiguration>().ToMethod(ctx => ConfigurationFactory.GetConfiguration<ICompanyRepositoryConfiguration>());
			DI.Kernel.Bind<IQuoteRepositoryConfiguration>().ToMethod(ctx => ConfigurationFactory.GetConfiguration<IQuoteRepositoryConfiguration>());
			DI.Kernel.Bind<IMarketViewerConfiguration>().ToMethod(ctx => ConfigurationFactory.GetConfiguration<IMarketViewerConfiguration>());
			DI.Kernel.Bind<IRatingsCrawlerConfiguration>().ToMethod(ctx => ConfigurationFactory.GetConfiguration<IRatingsCrawlerConfiguration>());
		}

		public static T Get<T>()
		{
			return DI.Kernel.Get<T>();
		}

		private static ICompanyRepository GetCompaniesRepository()
		{
			var configuration = DI.Kernel.Get<ICompanyRepositoryConfiguration>();

			var companiesRepository = new CompaniesRepository(configuration);

			companiesRepository.LoadCompanies();

			return companiesRepository;
		}

		private static IQuoteRepository GetQuotesRepository()
		{
			var configuration = DI.Kernel.Get<IQuoteRepositoryConfiguration>();
			var parser = DI.Kernel.Get<IParser>();
			var companyRepository = DI.Kernel.Get<ICompanyRepository>();

			var quotesRepository = new QuotesRepository(parser, companyRepository, configuration);

			quotesRepository.LoadQuotes();

			return quotesRepository;
		}
	}
}
